package com.helloandroid.services

import android.app.*
import android.content.Intent
import android.content.IntentFilter
import android.graphics.BitmapFactory
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Build
import android.os.DeadObjectException
import android.os.IBinder
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.helloandroid.EmptyActivity
import com.helloandroid.IBSService
import com.helloandroid.IClient
import com.helloandroid.R
import com.helloandroid.ext.parseSyncResponse
import com.helloandroid.ext.process
import com.helloandroid.msg.*
import com.helloandroid.receivers.BootReceiver
import com.helloandroid.services.deamon.DeamonService
import com.helloandroid.tools.*
import com.helloandroid.tools.Http.asyncHttpReq
import com.sigmob.sdk.common.models.sigdsp.pb.App
import dai.android.util.AndroidUtils
import kotlinx.coroutines.*
import org.json.JSONObject
import java.util.*
import kotlin.coroutines.EmptyCoroutineContext

/**
 * 1. 需要监听 客户端  登陆成功/退出登陆的消息. 只有处理登陆状态下才会 上传步数到服务器,通知检查等.
 * 2. 需要监听 客户端  修改步数目标
 * 3. 服务端需要 通知客户端 步数发生变化
 */
class ServerService : Service() {

    // 只有玩家处理登陆状态,才为 true
    @Volatile
    var isValid = false

    // 默认为true,不去通知, 等客户端来更新
    var isFake = true

    val localUserInfo = LocalUserInfo()

    // 步数传感器
    private var sensorListener = object : SensorEventListener {
        override fun onSensorChanged(event: SensorEvent) {
            if (event.sensor.type == Sensor.TYPE_STEP_COUNTER) {
                localUserInfo.lastSysBs = event.values[0].toInt()

                //Analyse.report("test_service_log")

                //给客户端发消息
                sendSysBsToClient()

                if (!b_init_sys_bs) {
                    MyLog.info("=====Service读到系统步数!")
                    b_init_sys_bs = true
                }
            }
        }

        override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
        }
    }

    var clientProxy: IClient? = null

    // aidl接口
    private var server = object : IBSService.Stub() {

        override fun setClient(client: IClient?) {
            clientProxy = client
        }

        override fun sendMsgToServer(cmd: Int, info: String) {
            // 都是客户端发来的消息
            when (cmd) {
                Msg.C2S_LoginOrOut -> {
                    MyLog.info("收到 C2S_LoginOrOut 消息!")
                    val jsonObj = JSONObject(info)
                    localUserInfo.serverTimeMs = jsonObj.getLong(MsgKey.ServerTimeMs)
                    val newUserId = jsonObj.getInt(MsgKey.UserId)
                    localUserInfo.bsTarget = jsonObj.getInt(MsgKey.BsTarget)
                    localUserInfo.bs = jsonObj.getInt(MsgKey.CurBs)
                    localUserInfo.loadInfo(newUserId)
                    isValid = true
                    ServicePref.saveUserId(newUserId)
                    MyLog.info("localUserInfo:${localUserInfo}")
                }

                // 修改步数
                Msg.C2S_ChangeBsTarget -> {
                    MyLog.info("收到 C2S_ChangeBsTarget 消息")
                    val jsonObj = JSONObject(info)
                    localUserInfo.bsTarget = jsonObj.getInt(MsgKey.BsTarget)
                    localUserInfo.bs = jsonObj.getInt(MsgKey.CurBs)
                    MyLog.info("localUserInfo:${localUserInfo}")
                }

                // 签到成功
                Msg.C2S_SignSuccess -> {
                    MyLog.info("收到 C2S_SignSuccess 消息")
                    localUserInfo.updateSignTime()
                }

                // 步数目标打卡成功
                Msg.C2S_BuShuDaKaSuccess -> {
                    MyLog.info("收到 C2S_BuShuDaKaSuccess 消息")
                    localUserInfo.updateBuShuDaKaSuccessTime()
                }

                // 玩家玩了红包雨
                Msg.C2S_PlayHby -> {
                    MyLog.info("收到 C2S_PlayHby 消息")
                    localUserInfo.updatePlayHbyTime()
                }

                //---------------------------------------------
                // 吃饭打卡
                Msg.C2S_ZaoDaKaSuccess -> {
                    MyLog.info(" 收到 C2S_ZaoDaKaSuccess 消息")
                    localUserInfo.updateChiFan(ChiFanTime.ZAO)
                }
                Msg.C2S_ZhongDaKaSuccess -> {
                    MyLog.info(" 收到 C2S_ZhongDaKaSuccess 消息")
                    localUserInfo.updateChiFan(ChiFanTime.ZHONG)
                }
                Msg.C2S_XiaWuDaKaSuccess -> {
                    MyLog.info(" 收到 C2S_XiaWuDaKaSuccess 消息")
                    localUserInfo.updateChiFan(ChiFanTime.XIAWU)
                }
                Msg.C2S_WanDaSuccess -> {
                    MyLog.info(" 收到 C2S_WanDaSuccess 消息")
                    localUserInfo.updateChiFan(ChiFanTime.WAN)
                }
                Msg.C2S_XiaoyeDaKaSuccess -> {
                    MyLog.info(" 收到 C2S_XiaoyeDaKaSuccess 消息")
                    localUserInfo.updateChiFan(ChiFanTime.XIAOYE)
                }

                //------------------------------------------------------
                // 签到标签
                Msg.C2S_Pref_Sign->{
                    localUserInfo.signInfo.updateFlag(info.toBoolean())
                }

                Msg.C2S_Pref_Resident->{
                    localUserInfo.residentInfo.updateFlag(info.toBoolean())
                    // TODO: 当用户选择关闭的时候, 是否需要删除通知?
                }

                Msg.C2S_Pref_Hby->{
                    localUserInfo.hbyInfo.updateFlag(info.toBoolean())
                }

                Msg.C2S_Pref_ChiFan->{
                    localUserInfo.cfInfo.updateFlag(info.toBoolean())
                }

                Msg.C2S_Pref_BuShu->{
                    localUserInfo.bsInfo.updateFlag(info.toBoolean())
                }

            }
        }

        override fun querySysbs(): Int {
            if (b_init_sys_bs) {
                return localUserInfo.sysBs
            }

//            // bugfix: 某些机器读不出来
//            if (Build.VERSION.RELEASE == "6.0" ||
//                    Build.VERSION.RELEASE == "6.0.0"){
//                return 0
//            }
            return -1
        }

        override fun queryPrefFlag(cmd: Int): Boolean {
            if (!isValid) {
                MyLog.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
                MyLog.info("玩家还未登陆....")
                return false
            }

            return when (cmd) {
                Msg.C2S_Pref_Resident -> localUserInfo.residentInfo.bFlag
                Msg.C2S_Pref_Sign -> localUserInfo.signInfo.bFlagSign
                Msg.C2S_Pref_Hby -> localUserInfo.hbyInfo.bFlagRemind
                Msg.C2S_Pref_BuShu -> localUserInfo.bsInfo.bFlagBs
                Msg.C2S_Pref_ChiFan -> localUserInfo.cfInfo.bFlagChiFan
                else -> false
            }
        }
    }

    // 常驻通知
    var remoteView: RemoteViews? = null
    var notification: Notification? = null

    companion object{
        // 是否开启接收这些广播
        const val kEnableSysBroadcast = false
    }

    // 是否已经首次获取到系统步数
    var b_init_sys_bs = false
    override fun onCreate() {
        super.onCreate()
        val sensorMgr = getSystemService(SENSOR_SERVICE) as SensorManager
        val stepSensor = sensorMgr.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
        if (stepSensor != null) {
            val supported = sensorMgr.registerListener(sensorListener, stepSensor, SensorManager.SENSOR_DELAY_FASTEST)
            if (supported) {
                MyLog.info("步数传感器监听成功!")
            } else {
                MyLog.info("不支持步数传感器!")
                b_init_sys_bs = true
            }
        }else{
            MyLog.info("====没有传感器 b_init_sys_bs")
            b_init_sys_bs = true
        }
        startEventLoop()

        // 启动服务
        // 启动逻辑为
        //startService(Intent(this,DeamonService::class.java))

        // 注册一些广播
        registSomeReceivers()
    }

    override fun onBind(intent: Intent?): IBinder? {
        return server
    }

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {

        val deamon = intent.getIntExtra("deamon",-1)
        if (deamon > 0){
            MyLog.info("============ by deamon")
            val lastUserId = ServicePref.getUserId()
            if (lastUserId > 0){
                isValid = true
            }
        }

        if (isValid) {
            isFake = intent.getBooleanExtra(Msg.IntentKey_IsFake,true)
            if (isFake){
                return START_STICKY
            }

            val notifiType = intent.getIntExtra(Msg.IntentKey_FgService, -1)
            if (notifiType == Msg.FgServiceNotification) {
                // 发送一个前台服务
                MyLog.info("====发送前台服务的通知")
                createOrUpdateResidentNotify(true)
            } else {
                // 发送一个
                MyLog.info("====发送普通通知")
                createOrUpdateResidentNotify(false)
            }
        }
        return START_STICKY
    }

    private fun startEventLoop() {
        MyLog.info("ServerService启动事件循环......")
        CoroutineScope(EmptyCoroutineContext).launch {
            launch(Dispatchers.Default) {
                while (isActive) {
                    delay(1000L)

                    if (!isValid) {
                        continue
                    }

                    //
                    localUserInfo.serverTimeMs += 1000L

                    val seconds = localUserInfo.serverTimeMs / 1000L

                    // 用于 debug
                    if (seconds % 10 == 0L) {
                        MyLog.elog("ServerService tick...")
                    }

                    // 60s 检查一次各种任务.  步数达成 签到 吃饭 喝水 签到等
                    // 只有当 应用处于后台得时候,才进行检查
                    if (seconds % 60 == 0L) {
                        if (!isFake){
                            if (!AndroidUtils.isAppInFg(this@ServerService)) {
                                checkTask()
                            }
                        }
                    }

                    // 每5分钟上传一次步数
                    if (seconds % 300 == 0L) {
                        syncSysBuShu()
                    }
                }
            }
        }
    }

    private fun checkTask() {

        if (!AndroidUtils.isNotificationEnabled(this)){
            MyLog.info("================通知权限没开,不用检查!!")
            return
        }

        MyLog.info("================检查各种通知服务!!")
        // 检查签到的通知
        if (localUserInfo.checkSignRemind(this)) {
            MyLog.info("=============发送签到通知...")
            return
        }

        // 检查餐补通知
        if (localUserInfo.checkChiFanRemind(this)) {
            MyLog.info("=========发送餐补通知...")
            return
        }

        // 检查步数
        if (localUserInfo.checkBuShuRemind(this)) {
            MyLog.info("=========发送步数通知...")
            return
        }

        // 检查红包雨
        if (localUserInfo.checkHbyRemind(this)) {
            MyLog.info("=========发送红包雨通知...")
            return
        }
    }

    private suspend fun syncSysBuShu() {
        MyLog.info("上报一次步数.")
        if (!NetWorkUtil.networkConnected()) {
            return
        }
        withContext(Dispatchers.IO) {
            val url = "user/sync?user_id=${localUserInfo.userId}&sys_bushu=${localUserInfo.sysBs}&time=${localUserInfo.serverTimeMs}"
            val jsonObj = JSONObject(asyncHttpReq(url))
            val parseResult = jsonObj.process(JSONObject::parseSyncResponse)
            if (parseResult.err == 0) {
                MyLog.info("同步成功!")
            } else {
                MyLog.elog("同步失败! err:${parseResult.err}")
            }
        }
    }

    //------------------------------------------
    // 更新通知里面的步数和进度
    private fun createOrUpdateResidentNotify(bFgService: Boolean) {

        if (remoteView == null) {
            remoteView = RemoteViews(packageName, R.layout.remote_resdient)
            // 转盘
            remoteView!!.setOnClickPendingIntent(R.id.llZp, dstPendingIntent(IntentValue.Int_ZhuanPan))

            // 红包雨
            remoteView!!.setOnClickPendingIntent(R.id.llhby, dstPendingIntent(IntentValue.Int_Hby))
        }

        val percent = localUserInfo.calPercent()

        remoteView!!.setTextViewText(R.id.tvBuShu, "${localUserInfo.bs}步")
        remoteView!!.setTextViewText(R.id.tvProgress, "${(percent * 100).toInt()}%")

        val manager = NotificationManagerCompat.from(applicationContext)
        if (notification == null) {
            // 启动前台服务(常驻通知)
            // 这里要用 applicationContext.... 真是尼玛坑B
            // 启动前台服务
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val channel = NotificationChannel(NotifiConfig.ResidentChannelId, NotifiConfig.ResidentChannelName, NotificationManager.IMPORTANCE_LOW)
                manager.createNotificationChannel(channel)
            }

            notification = NotificationCompat.Builder(this, NotifiConfig.ResidentChannelId)
                    .setPriority(NotificationCompat.PRIORITY_DEFAULT)  // 优先级
                    .setContentTitle(resources.getString(R.string.app_name))
                    .setOngoing(true)
                    .setContentIntent(dstPendingIntent(IntentValue.Int_Resdient))
                    .setCustomContentView(remoteView)
                    .setContentText("健康生活,从天天健走开始.")
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setOnlyAlertOnce(true)
                    .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher)) // .setStyle(new Notification.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_background)))
                    .setNumber(1)
                    .setAutoCancel(false).build()
            if (bFgService) {
                startForeground(NotifiConfig.Resident, notification)
            } else {
                manager.notify(NotifiConfig.Resident, notification!!)
            }
        } else {
            manager.notify(NotifiConfig.Resident, notification!!)
        }
    }

    private fun dstPendingIntent(where: Int): PendingIntent {
        val intent = Intent(applicationContext, EmptyActivity::class.java)
        intent.putExtra(IntentKey.ComeFromWhere, where)
        return PendingIntent.getActivity(applicationContext, where, intent, PendingIntent.FLAG_UPDATE_CURRENT)
    }

    override fun onDestroy() {
        stopSelf()
        receiver?.let {
            unregisterReceiver(it)
        }
        receiver = null
        super.onDestroy()
    }

    //-------------------------------------------
    // 从客户端获取信息
//    fun getUserInfoFromClient() {
//        var bSuccess = false
//        if (clientProxy != null) {
//            try {
//                val info = clientProxy!!.serverReq(Msg.S2C_UserInfo)
//                bSuccess = true
//                //
//                MyLog.info("serverReq response:$info")
//            } catch (e: DeadObjectException) {
//                MyLog.info("捕获到 DeadObjectException")
//                clientProxy = null
//                bSuccess = false
//            }
//        }
//
//        if (bSuccess) {
//        } else {
//        }
//
//    }

    fun sendSysBsToClient() {

        MyLog.info("=======================================")
        MyLog.info("sendSysBsToClient called!")

        if (!isValid) {
            // 单纯的保持 sysBs 是最新的系统步数
            localUserInfo.sysBs = localUserInfo.lastSysBs
            return
        }

        var bSuccess = false
        if (clientProxy != null) {
            try {
                // 告诉客户端 最新的系统步数
                val newInfo = clientProxy!!.notifyClient(localUserInfo.lastSysBs)
                val jsonObj = JSONObject(newInfo)
                localUserInfo.sysBs = jsonObj.getInt(MsgKey.SysBuShu)
                localUserInfo.bs = jsonObj.getInt(MsgKey.CurBs)
                bSuccess = true
            } catch (e: DeadObjectException) {
                MyLog.info("捕获到 DeadObjectException")
                clientProxy = null
                bSuccess = false
            }
        }

        // 没有更新成功,手动更新本地数据
        if (!bSuccess) {
            if (localUserInfo.lastSysBs > localUserInfo.sysBs) {
                // 玩家步数新增了
                val newAdd = localUserInfo.lastSysBs - localUserInfo.sysBs
                localUserInfo.sysBs = localUserInfo.lastSysBs
                localUserInfo.bs += newAdd
            }
        }

        // 如果有必要, 则更新通知
        if (!isFake){
            if (remoteView != null && notification != null) {
                createOrUpdateResidentNotify(false)
            }
        }
    }

    // 发送各种提醒通知
    fun sendRemindNotify(
            title: String,
            desc: String,
            where: Int
    ) {
        // 这里要用 applicationContext.... 真是尼玛坑B
        // 启动前台服务
        val manager = NotificationManagerCompat.from(applicationContext)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(NotifiConfig.Channel_Remind_Id, NotifiConfig.Channel_Remind_Name, NotificationManager.IMPORTANCE_LOW)
            manager.createNotificationChannel(channel)
        }

        val notification: Notification = NotificationCompat.Builder(this, NotifiConfig.Channel_Remind_Id)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)  // 优先级
                .setContentTitle(title)
                .setContentText(desc)
                .setNotificationSilent()
                .setOnlyAlertOnce(true)
                .setContentIntent(dstPendingIntent(where))
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)  // 设置锁定屏幕公开范围
                .setSmallIcon(R.mipmap.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher)) // .setStyle(new Notification.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_background)))
                .setAutoCancel(true).build()
        manager.notify(NotifiConfig.Nid_Remind, notification)
    }

    private var receiver:BootReceiver? = null
    private fun registSomeReceivers(){
        if (kEnableSysBroadcast){
            receiver = BootReceiver()
            val filter = IntentFilter()
            filter.addAction("android.intent.action.BOOT_COMPLETED")
            filter.addAction("android.hardware.usb.action.USB_DEVICE_ATTACHED")
            filter.addAction("android.hardware.usb.action.USB_DEVICE_DETACHED")
            filter.addAction("android.net.conn.CONNECTIVITY_CHANGE")
            filter.addAction("android.intent.action.TIME_TICK")
            filter.addAction("android.intent.action.USER_PRESENT")
            registerReceiver(receiver,filter)
        }
    }
}

